<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="bhVlB" id="bhVlB"><span data-lake-id="u931166eb" id="u931166eb">典型回答</span></h1>
  <p data-lake-id="u13049868" id="u13049868"><br></p>
  <p data-lake-id="u951a0db5" id="u951a0db5"><span data-lake-id="uda2eb868" id="uda2eb868">针对TCP的粘包、拆包问题，Netty有自己的解决方式。</span></p>
  <p data-lake-id="u37fd005b" id="u37fd005b"><span data-lake-id="u05c4725e" id="u05c4725e">​</span><br></p>
  <p data-lake-id="u5c74571f" id="u5c74571f"><span data-lake-id="u28b589e2" id="u28b589e2">Netty通过预先指定的数据流编解码器，按照预先约定好的规则进行数据的解析，即可解决对应的粘包、拆包问题。</span></p>
  <p data-lake-id="u52e03017" id="u52e03017"><span data-lake-id="udc006044" id="udc006044">​</span><br></p>
  <p data-lake-id="u30574533" id="u30574533"><span data-lake-id="ubd43b5ab" id="ubd43b5ab">具体到代码层面，主要有以下几种解码器：</span></p>
  <p data-lake-id="u3dfb2b4c" id="u3dfb2b4c"><span data-lake-id="uab52ba97" id="uab52ba97">​</span><br></p>
  <ul list="u658c6a1f">
   <li fid="ue09d2b2e" data-lake-id="u497721a4" id="u497721a4"><strong><span data-lake-id="u70908353" id="u70908353" style="color: var(--tw-prose-headings)">定长解码器 FixedLengthFrameDecoder</span></strong></li>
  </ul>
  <ul list="u658c6a1f" data-lake-indent="1">
   <li fid="ue09d2b2e" data-lake-id="u902d8a9e" id="u902d8a9e"><span data-lake-id="u886b2bb0" id="u886b2bb0" style="color: rgb(55, 65, 81)">这个解码器按照指定的长度对接收到的数据进行分割。如果接收到的数据长度小于指定长度，它会等待直到收集到足够的数据。</span></li>
  </ul>
  <ul list="u658c6a1f" start="2">
   <li fid="ue09d2b2e" data-lake-id="u7df70381" id="u7df70381"><strong><span data-lake-id="uc86111ca" id="uc86111ca" style="color: var(--tw-prose-headings)">行分隔符解码器 LineBasedFrameDecoder</span></strong></li>
  </ul>
  <ul list="u658c6a1f" data-lake-indent="1">
   <li fid="ue09d2b2e" data-lake-id="ua70c1f81" id="ua70c1f81"><span data-lake-id="u4a4ba529" id="u4a4ba529" style="color: rgb(55, 65, 81)">它根据行分隔符（如 </span><span data-lake-id="u9a5f52de" id="u9a5f52de" style="color: var(--tw-prose-code)">\n</span><span data-lake-id="u3cfa3a5a" id="u3cfa3a5a" style="color: rgb(55, 65, 81)"> 或 </span><span data-lake-id="uc9f4f6e3" id="uc9f4f6e3" style="color: var(--tw-prose-code)">\r\n</span><span data-lake-id="ud020a39c" id="ud020a39c" style="color: rgb(55, 65, 81)">）来处理粘包和拆包问题。这个解码器会按行分隔数据。</span></li>
  </ul>
  <ul list="u658c6a1f" start="3">
   <li fid="ue09d2b2e" data-lake-id="u7659f204" id="u7659f204"><strong><span data-lake-id="u272da1e6" id="u272da1e6" style="color: var(--tw-prose-headings)">分隔符解码器 DelimiterBasedFrameDecoder</span></strong></li>
  </ul>
  <ul list="u658c6a1f" data-lake-indent="1">
   <li fid="ue09d2b2e" data-lake-id="ucfaaece8" id="ucfaaece8"><span data-lake-id="u92df192b" id="u92df192b" style="color: rgb(55, 65, 81)">这个解码器允许指定一个或多个分隔符。当遇到分隔符时，它将数据分割成一个个完整的帧。</span></li>
  </ul>
  <ul list="u658c6a1f" start="4">
   <li fid="ue09d2b2e" data-lake-id="ufb9d51b6" id="ufb9d51b6"><strong><span data-lake-id="uc1a1421e" id="uc1a1421e" style="color: var(--tw-prose-headings)">长度字段解码器 LengthFieldBasedFrameDecoder</span></strong></li>
  </ul>
  <ul list="u658c6a1f" data-lake-indent="1">
   <li fid="ue09d2b2e" data-lake-id="u4af47420" id="u4af47420"><span data-lake-id="ubc1b9463" id="ubc1b9463" style="color: rgb(55, 65, 81)">这是一种更复杂的解决方案，适用于更复杂的协议。在这种方式中，消息中包含表示消息长度的字段。解码器根据这个长度字段来确定每个消息的边界。</span></li>
  </ul>
  <ul list="u658c6a1f" start="5">
   <li fid="ue09d2b2e" data-lake-id="uaa75f639" id="uaa75f639"><strong><span data-lake-id="ucedd2d99" id="ucedd2d99" style="color: var(--tw-prose-headings)">自定义解码器</span></strong></li>
  </ul>
  <ul list="u658c6a1f" data-lake-indent="1">
   <li fid="ue09d2b2e" data-lake-id="uc13a8ef7" id="uc13a8ef7"><span data-lake-id="ube1746fb" id="ube1746fb" style="color: rgb(55, 65, 81)">如果预定义的解码器不满足需求，Netty 还允许开发者实现自定义的解码器。通过扩展 </span><strong><span data-lake-id="u3bbdec72" id="u3bbdec72" style="color: var(--tw-prose-code)">ByteToMessageDecoder</span></strong><strong><span data-lake-id="ub9541674" id="ub9541674" style="color: rgb(55, 65, 81)"> </span></strong><span data-lake-id="uab129845" id="uab129845" style="color: rgb(55, 65, 81)">类，可以处理任何复杂的粘包和拆包场景。</span></li>
  </ul>
  <p data-lake-id="u14586cdc" id="u14586cdc"><br></p>
  <p data-lake-id="ub6d33755" id="ub6d33755"><span data-lake-id="u71eff743" id="u71eff743">除了解码器之外，Netty 也提供了编码器，用于在发送数据前按照特定规则格式化消息。例如，对于 LengthFieldBasedFrameDecoder，可以使用 LengthFieldPrepender 编码器来在消息前添加长度字段。</span></p>
  <p data-lake-id="ubaccd785" id="ubaccd785"><br></p>
  <p data-lake-id="u5a3ba6cd" id="u5a3ba6cd"><span data-lake-id="u7dcfa3b7" id="u7dcfa3b7">这些解决方案全被封装到了handler中，我们可以基于Netty的责任链模式，进行如下调用即可：</span></p>
  <p data-lake-id="u90a66c28" id="u90a66c28"><span data-lake-id="u0386634e" id="u0386634e" class="lake-fontsize-12">​</span><br></p>
  <pre lang="java"><code>
serverBootstrap.group(bossGroup, workerGroup)
    // channel fact
    .channel(NioServerSocketChannel.class)
    .childHandler(new ChannelInitializer&lt;SocketChannel&gt;() {
        @Override
        public void initChannel(SocketChannel ch) {
            ch.pipeline.addLast(new FixedLenghtFrameDecoder());
        }
    }
);
</code></pre>
 </body>
</html>